import com.sun.jndi.cosnaming.CNCtx;
import dao.DAOFactory;
import dao.impl.MemDAOFactory;
import handler.*;
import handler.commandprocessor.*;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import message.Command;
import message.CommandType;
import route.Router;
import route.RouterImpl;

import java.util.EnumMap;

public class Server
{
    public static void main(String[] args) throws InterruptedException
    {
        DAOFactory      daoFactory      = new MemDAOFactory();
        final Router    router          = new RouterImpl(daoFactory.getGroupDAO(), daoFactory.getRelationDAO());
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.channel(NioServerSocketChannel.class);
        serverBootstrap.group(new NioEventLoopGroup(1), new NioEventLoopGroup());
        //handler方法传入的处理器工作在服务端监听链接上
        serverBootstrap.handler(new ChannelInboundHandlerAdapter()
        {
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
            {
                System.out.println("msg对象是一个SocketChannel：" + (msg instanceof SocketChannel));
                ctx.fireChannelRead(msg);
            }
        });
        final EnumMap<CommandType, CommandHandler.CommandProcessor> enumMap = new EnumMap<CommandType, CommandHandler.CommandProcessor>(CommandType.class);
        enumMap.put(CommandType.LOGIN, new LoginProcessor(daoFactory.getClientDAO(), router));
        enumMap.put(CommandType.REGISTER, new RegisterProcessor(daoFactory.getClientDAO(), router));
        enumMap.put(CommandType.CREATE_GROUP, new CreateGroupProcessor(daoFactory.getGroupDAO(), daoFactory.getRelationDAO(), router));
        enumMap.put(CommandType.JOIN_GROUP, new JoinGroupProcessor(daoFactory.getGroupDAO(), daoFactory.getRelationDAO(), router));
        enumMap.put(CommandType.SEND_TO_CLIENT, new SendToClientProcessor(daoFactory.getClientDAO(), router));
        enumMap.put(CommandType.SEND_TO_GROUP, new SendToGroupProcessor(router));
        enumMap.put(CommandType.HEART_BEAT, new HeartBeatProcessor());
        serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>()
        {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception
            {
                ch.pipeline().addLast(new IdleStateHandler(2, 0, 0));
                ch.pipeline().addLast(new ClientIdleHandler());
                ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4));
                ch.pipeline().addLast(new CommandDecoder());
                ch.pipeline().addLast(new CommandHandler(enumMap));
                ch.pipeline().addLast(new OfflineHandler(router));
                ch.pipeline().addLast(new MessageEncoder());
                ch.pipeline().addLast(new ReceiveEncoder());
            }
        });
        ChannelFuture future = serverBootstrap.bind(8888);
        future.sync();
        future.channel().closeFuture().sync();
    }
}
